home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / X11 / wais / waisgate / HTRules.c < prev    next >
C/C++ Source or Header  |  1995-05-09  |  8KB  |  297 lines

  1. /*    Configuration manager for Hypertext Daemon        HTRules.c
  2. **    ==========================================
  3. **
  4. **
  5. ** History:
  6. **     3 Jun 91    Written TBL
  7. **    10 Aug 91    Authorisation added after Daniel Martin (pass, fail)
  8. **            Rule order in file changed
  9. **            Comments allowed with # on 1st char of rule line
  10. **      17 Jun 92       Bug fix: pass and fail failed if didn't contain '*' TBL
  11. */
  12.  
  13. /* (c) CERN WorldWideWeb project 1990,91. See Copyright.html for details */
  14. #include "HTRules.h"
  15.  
  16. #include <stdio.h>
  17. #include "HTUtils.h"
  18. #include "tcp.h"
  19. #include "HTFile.h"
  20.  
  21. #define LINE_LENGTH 256
  22.  
  23.  
  24. typedef struct _rule {
  25.     struct _rule *    next;
  26.     HTRuleOp    op;
  27.     char *        pattern;
  28.     char *        equiv;
  29. } rule;
  30.  
  31. /*    Module-wide variables
  32. **    ---------------------
  33. */
  34.  
  35. PRIVATE rule * rules = 0;    /* Pointer to first on list */
  36. #ifndef PUT_ON_HEAD
  37. PRIVATE rule * rule_tail = 0;    /* Pointer to last on list */
  38. #endif
  39.  
  40. /*    Add rule to the list                    HTAddRule()
  41. **    --------------------
  42. **
  43. **  On entry,
  44. **    pattern        points to 0-terminated string containing a single "*"
  45. **    equiv        points to the equivalent string with * for the
  46. **            place where the text matched by * goes.
  47. **  On exit,
  48. **    returns        0 if success, -1 if error.
  49. */
  50. /*    Note that if BYTE_ADDRESSING is set, the three blocks required
  51. **    are allocated and deallocated as one. This will save time and
  52. **    storage, when malloc's allocation units are large.
  53. */
  54. #ifdef __STDC__
  55. PUBLIC int HTAddRule (HTRuleOp op, const char * pattern, const char * equiv)
  56. #else
  57. int HTAddRule(op, pattern, equiv)
  58.     HTRuleOp    op;
  59.     char *    pattern;
  60.     char *    equiv;
  61. #endif
  62. {
  63. #ifdef BYTE_ADDRESSING    /* economise on malloc() blocks */
  64.     int        length_of_pattern = strlen(pattern)+1;
  65.     rule *    temp = malloc(sizeof(*temp) +
  66.                 size_of_pattern + strlen(equiv) + 1);
  67.     char *    pPattern = (char *) &temp[1];
  68. #else
  69.     rule *    temp = (rule *)malloc(sizeof(*temp));
  70.     char *    pPattern = (char *)malloc(strlen(pattern)+1);
  71. #endif
  72.  
  73.     if (equiv) {        /* Two operands */
  74. #ifdef BYTE_ADDRESSING    /* economise on malloc() blocks */
  75.         char *    pEquiv = pPattern + length_of_pattern;
  76. #else
  77.     char *    pEquiv = (char *)malloc(strlen(equiv)+1);
  78. #endif
  79.         temp->equiv = pEquiv;
  80.         strcpy(pEquiv, equiv);
  81.     } else {
  82.         temp->equiv = 0;
  83.     }
  84.     temp->pattern = pPattern;
  85.     temp->op = op;
  86.  
  87.     strcpy(pPattern, pattern);
  88.     if (TRACE) printf("Rule: For `%s' op %i `%s'\n", pattern, op, equiv);
  89.  
  90. #ifdef PUT_ON_HEAD
  91.     temp->next = rules;
  92.     rules = temp;
  93. #else
  94.     temp->next = 0;
  95.     if (rule_tail) rule_tail->next = temp;
  96.     else rules = temp;
  97.     rule_tail = temp;
  98. #endif
  99.  
  100.         
  101.     return 0;
  102. }
  103.  
  104.  
  105. /*    Clear all rules                        HTClearRules()
  106. **    ---------------
  107. **
  108. ** On exit,
  109. **    There are no rules
  110. **    returns        0 if success, -1 if error.
  111. **
  112. ** See also
  113. **    HTAddRule()
  114. */
  115. #ifdef __STDC__
  116. int HTClearRules(void)
  117. #else
  118. int HTClearRules()
  119. #endif
  120. {
  121.     while (rules) {
  122.         rule * temp = rules;
  123.     rules = temp->next;
  124. #ifdef BYTE_ADDRESSING
  125.     free(temp);
  126. #else
  127.     free(temp->pattern);
  128.     free(temp->equiv);
  129.     free(temp);
  130. #endif
  131.     }
  132. #ifndef PUT_ON_HEAD
  133.     rule_tail = 0;
  134. #endif
  135.  
  136.     return 0;
  137. }
  138.  
  139.  
  140. /*    Translate by rules                    HTTranslate()
  141. **    ------------------
  142. **
  143. **    The most recently defined rules are applied first.
  144. **
  145. ** On entry,
  146. **    required    points to a string whose equivalent value is neeed
  147. ** On exit,
  148. **    returns        the address of the equivalent string allocated from
  149. **            the heap which the CALLER MUST FREE. If no translation
  150. **            occured, then it is a copy of te original.
  151. */
  152. #ifdef __STDC__
  153. char * HTTranslate(const char * required)
  154. #else
  155. char * HTTranslate(required)
  156.     char * required;
  157. #endif
  158. {
  159.     rule * r;
  160.     char * current = (char *)malloc(strlen(required)+1);
  161.     strcpy(current, required);
  162.     
  163.     for(r = rules; r; r = r->next) {
  164.         char * p = r->pattern;
  165.     int m;   /* Number of characters matched against wildcard */
  166.     CONST char * q = current;
  167.     for(;*p && *q; p++, q++) {   /* Find first mismatch */
  168.         if (*p!=*q) break;
  169.     }
  170.  
  171.     if (*p == '*') {        /* Match up to wildcard */
  172.         m = strlen(q) - strlen(p+1); /* Amount to match to wildcard */
  173.         if(m<0) continue;           /* tail is too short to match */
  174.         if (0!=strcmp(q+m, p+1)) continue;    /* Tail mismatch */
  175.     } else                 /* Not wildcard */
  176.         if (*p != *q) continue;    /* plain mismatch: go to next rule */
  177.  
  178.     switch (r->op) {        /* Perform operation */
  179.     case HT_Pass:                /* Authorised */
  180.             if (!r->equiv) {
  181.             if (TRACE) printf("HTRule: Pass `%s'\n", current);
  182.             return current;
  183.             }
  184.         /* Fall through ...to map and pass */
  185.         
  186.     case HT_Map:
  187.         if (*p == *q) { /* End of both strings, no wildcard */
  188.                   if (TRACE) printf(
  189.                    "For `%s' using `%s'\n", current, r->equiv);  
  190.               StrAllocCopy(current, r->equiv); /* use entire translation */
  191.         } else {
  192.           char * ins = strchr(r->equiv, '*');    /* Insertion point */
  193.               if (ins) {    /* Consistent rule!!! */
  194.             char * temp = (char *)malloc(
  195.                 strlen(r->equiv)-1 + m + 1);
  196.             strncpy(temp,     r->equiv, ins-r->equiv);
  197.             /* Note: temp may be unterminated now! */
  198.             strncpy(temp+(ins-r->equiv), q, m);  /* Matched bit */
  199.             strcpy (temp+(ins-r->equiv)+m, ins+1);    /* Last bit */
  200.                 if (TRACE) printf("For `%s' using `%s'\n",
  201.                         current, temp);
  202.             free(current);
  203.             current = temp;            /* Use this */
  204.  
  205.             } else {    /* No insertion point */
  206.             char * temp = (char *)malloc(strlen(r->equiv)+1);
  207.             strcpy(temp, r->equiv);
  208.                 if (TRACE) printf("For `%s' using `%s'\n",
  209.                         current, temp);
  210.             free(current);
  211.             current = temp;            /* Use this */
  212.             } /* If no insertion point exists */
  213.         }
  214.         if (r->op == HT_Pass) {
  215.             if (TRACE) printf("HTRule: ...and pass `%s'\n", current);
  216.             return current;
  217.         }
  218.         break;
  219.  
  220.         case HT_Invalid:
  221.         case HT_Fail:                /* Unauthorised */
  222.                 if (TRACE) printf("HTRule: *** FAIL `%s'\n", current);
  223.             return (char *)0;
  224.                         
  225.             } /* if tail matches ... switch operation */
  226.  
  227.     } /* loop over rules */
  228.  
  229.  
  230.     return current;
  231. }
  232.  
  233.  
  234.  
  235. /*    Load the rules from a file                HtLoadRules()
  236. **    --------------------------
  237. **
  238. ** On entry,
  239. **    Rules can be in any state
  240. ** On exit,
  241. **    Any existing rules will have been kept.
  242. **    Any new rules will have been loaded on top, so as to be tried first.
  243. **    Returns        0 if no error.
  244. **
  245. ** Bugs:
  246. **    The strings may not contain spaces.
  247. */
  248.  
  249. int HTLoadRules ARGS1(CONST char *, filename)
  250. {
  251.     FILE * fp = fopen(filename, "r");
  252.     char line[LINE_LENGTH+1];
  253.     char pattern[LINE_LENGTH+1];
  254.     char operation [LINE_LENGTH+1];
  255.     char equiv[LINE_LENGTH+1];
  256.     float quality;
  257.     int status;
  258.     
  259.     if (!fp) {
  260.         if (TRACE) printf("HTRules: Can't open rules file %s\n", filename);
  261.     return -1; /* File open error */
  262.     }
  263.     for(;;) {
  264.         HTRuleOp op;
  265.     if (!fgets(line, LINE_LENGTH+1, fp)) break;    /* EOF or error */
  266.     
  267.     {
  268.         char * p = strchr(line, '#');    /* Chop off comments */
  269.         if (p) *p = 0;
  270.     }
  271.     status = sscanf(line, "%256s%256s%256s%f",
  272.         operation, pattern, equiv, &quality);
  273.     if (status<=0) continue;    /* Comment only or blank */    
  274.     if (status<2) {
  275.         fprintf(stderr, "HTRule: Insufficient operands: %s\n", line);
  276.         return -2;    /*syntax error */
  277.     }
  278.     
  279.     if (0==strcasecomp(operation, "suffix")) {
  280.         HTSetSuffix(pattern, equiv, quality);
  281.     } else {
  282.         op =    0==strcasecomp(operation, "map")  ?    HT_Map
  283.         :    0==strcasecomp(operation, "pass") ?    HT_Pass
  284.         :    0==strcasecomp(operation, "fail") ?    HT_Fail
  285.         :                        HT_Invalid;
  286.         if (op==HT_Invalid) {
  287.         fprintf(stderr, "HTRule: Bad rule `%s'\n", line);
  288.         /* return -2; */
  289.         } else {  
  290.             HTAddRule(op, pattern, status > 2 ? equiv : NULL);
  291.         } 
  292.     }
  293.     }
  294.     fclose(fp);
  295.     return 0;        /* No error */
  296. }
  297.